/****************************************************************************
 * Chariott - Continuous Integration Testing Tool
 * Zaid Mohsin
 * The University of York
 * 2012/2013
 * MSc in Information Technology
 * All rights reserved.
 ****************************************************************************/
package chariott.partition;

import java.util.ArrayList;
import java.util.HashMap;

import java.util.Map;

import org.apache.commons.collections.MultiHashMap;
import org.apache.commons.collections.MultiMap;
import org.jdom2.Element;

import chariott.testing.RunItem;

/**
 * an implementation of AlgorithmOrder that orders the run items by Lease Used
 * Node algorithm.
 * 
 * @author Zaid
 * 
 */
public class LeastUsedOrder extends AlgorithmOrder {

	private Map<Integer, Double> weightsMap;
	// map to specifiy with run should go to which node
	private MultiMap sortingMap;

	public LeastUsedOrder(int numOfNodes, ArrayList<RunItem> itemsToRun) {
		super(numOfNodes, itemsToRun);
		weightsMap = new HashMap<Integer, Double>();
		sortingMap = new MultiHashMap();

		for (int i = 0; i < numOfNodes; i++)
			weightsMap.put(i, 0.0);

	}

	public MultiMap generateRuns() {

		ArrayList<Element> elementsGenerated = new ArrayList();

		for (int i = 0; i < itemsToRun.size(); i++) {
			Object myRun = itemsToRun.get(i);

			double itemWeight = 0;

			RunItem myItem = (RunItem) myRun;
			itemWeight = myItem.getWeight();

			// first check if the first items are bounded to the instances
			if (i < numOfNodes) {
				sortingMap.put(i, itemsToRun.get(i));
				weightsMap.put(i, weightsMap.get(i) + itemWeight);
			}
			// order the rest of the items according to the least used instance
			else {
				double smallestWeight = weightsMap.get(0);
				int smallestWeightNodeIndex = 0;

				for (int j = 0; j < numOfNodes; j++) {
					if (weightsMap.get(j) < smallestWeight) {
						smallestWeight = weightsMap.get(j);
						smallestWeightNodeIndex = j;
					}
				}

				//
				sortingMap.put(smallestWeightNodeIndex, itemsToRun.get(i));
				weightsMap.put(smallestWeightNodeIndex,
						weightsMap.get(smallestWeightNodeIndex) + itemWeight);

			}
		}

		return sortingMap;

	}

}
